// Paketinė OS, II variantas
// Edmundas Drūteika
// Vytautas Bačiulis

import java.io.*;

class ReadWrite {
    static String[] readCode(String file) {
        String[] lines_array = new String[260];

        try {
            int i = 0;
            String line;

            BufferedReader br = new BufferedReader(new FileReader(file));

            while ((line = br.readLine()) != null) {
                line = line.trim();
                if (line.length() != 0) {
                    lines_array[i] = line;
                    i++;
                }
            }

            br.close();
        }
        catch (IOException e) {
            System.err.println("Error: " + e.getMessage());
        }

        return lines_array;
    }

    static void readInput(Machine machine, LongObject[] VMMemory, int inputType) {
        int filledDSCounter = 0;

        if (inputType == 1) { // Informacija nuskaitoma po žodį (kiekvienas simbolis dedamas į atitinkamą žodžio baitą).
            try {
                int i = 0;
                int characterASCII;
                long characterValue, value;
                FileReader fr = new FileReader("IN.txt");

                while ((characterASCII = fr.read()) != -1) {
                    if (filledDSCounter == 128) { // DS visiškai užpildytas, tačiau yra dar neįrašytų reikšmių.
                        machine.changeIOI(1L);
                        fr.close();
                        break;
                    }

                    if (characterASCII >= 0 && characterASCII <= 255) { // Tinkamas simbolis.
                        characterValue = (long) characterASCII;

                        if (i == 0) { // Simbolį įrašome į pirmą baitą.
                            VMMemory[128+filledDSCounter].changeValue(characterValue*256L*256L*256L);
                            i++;
                        }
                        else if (i == 1) { // Simbolį įrašome į antrą baitą.
                            value = VMMemory[128+filledDSCounter].getValue();
                            VMMemory[128+filledDSCounter].changeValue(value+characterValue*256L*256L);
                            i++;
                        }
                        else if (i == 2) { // Simbolį įrašome į trečią baitą.
                            value = VMMemory[128+filledDSCounter].getValue();
                            VMMemory[128+filledDSCounter].changeValue(value+characterValue*256L);
                            i++;
                        }
                        else if (i == 3) { // Simbolį įrašome į ketvirtą baitą.
                            value = VMMemory[128+filledDSCounter].getValue();
                            VMMemory[128+filledDSCounter].changeValue(value+characterValue);
                            i = 0;
                            filledDSCounter++;
                        } else {
                            System.out.println("Klaida! Metode readInput, naudojant parametrą 1, įvyko klaida!");
                        }
                    } else { // Neleistinas simbolis.
                        machine.changeIOI(1L);
                        fr.close();
                        break;
                    }
                }

                fr.close();
            }
            catch (IOException e) {
                machine.changeIOI(1L);
//                System.out.println("Error: " + e.getMessage());
            }
        }
        else if (inputType == 2) { // Kiekvienas simbolis (įskaitant naujos eilutės simbolį) nuskaitomas į atskirą žodį.
            try {
                FileReader fr = new FileReader("IN.txt");
                int characterASCII;

                while ((characterASCII = fr.read()) != -1) {
                    if (filledDSCounter == 128) { // DS visiškai užpildytas, tačiau yra dar neįrašytų reikšmių.
                        machine.changeIOI(1L);
                        fr.close();
                        break;
                    }

                    if (characterASCII >= 0 && characterASCII <= 255) {
                        VMMemory[128+filledDSCounter].changeValue((long) characterASCII);
                        filledDSCounter++;
                    } else { // Neleistinas simbolis.
                        machine.changeIOI(1L);
                        fr.close();
                        break;
                    }
                }

                fr.close();
            }
            catch (IOException e) {
                machine.changeIOI(1L);
//                System.out.println("Error: " + e.getMessage());
            }
        }
        else if (inputType == 3) { // Ženklais „ENTER“ atskirti skaičiai yra įrašomi į atskirus žodžius.
            int i = 0;
            String[] input = readCode("IN.txt");

            while (input[i] != null) {
                if (filledDSCounter == 128) { // DS visiškai užpildytas, tačiau yra dar neįrašytų reikšmių.
                    machine.changeIOI(1L);
                    break;
                }

                if (isNumeric(input[i])) {
                    VMMemory[128+filledDSCounter].changeValue(Long.parseLong(input[i]));
                    filledDSCounter++;
                } else {
                    machine.changeIOI(1L);
                    break;
                }

                i++;
            }
        } else {
            System.out.println("\nKlaida! Metodui readInput perduotas nepalaikomas duomenų nuskaitymo tipas.");
            System.out.println("Palaikomi tipai: 1, 2, 3. | Perduota reikšmė: " + inputType + ".");
        }
    }

    static void writeOutput(Machine machine, LongObject[] VMMemory, int startPosition, int outputType) {
        if (outputType == 1) { // Kiekvienas žodžio baitas yra įrašomas kaip simbolis pagal ASCII kodų lentelę.
            try {
                FileWriter fw = new FileWriter("OUT.txt", true);
                int i = startPosition;
                long value = VMMemory[128+startPosition].getValue();
                int firstByte, secondByte, thirdByte, fourthByte;

                while (value != 0L && i < 128) {
                    firstByte = (int) (value/16777216L);
                    secondByte = (int) ((value/65536L) % 256L);
                    thirdByte = (int) ((value % 65536L)/256L);
                    fourthByte = (int) ((value % 65536L) % 256L);

                    if (firstByte != 0) {
                        fw.write(firstByte);
                    }
                    if (secondByte != 0) {
                        fw.write(secondByte);
                    }
                    if (thirdByte != 0) {
                        fw.write(thirdByte);
                    }
                    if (fourthByte != 0) {
                        fw.write(fourthByte);
                    }

                    i++;
                    value = VMMemory[128+i].getValue();
                }

                fw.close();
            }
            catch (IOException e) {
                machine.changeIOI(1L);
//                System.out.println("Error: " + e.getMessage());
            }
        }
        else if (outputType == 2) { // Kiekvienas žodis yra įrašomas kaip simbolis pagal ASCII kodų lentelę.
            try {
                FileWriter fw = new FileWriter("OUT.txt", true);
                int i = startPosition;
                int value = (int) VMMemory[128+i].getValue();

                while (value != 0 && i < 128) {
                    fw.write(value);
                    i++;
                    value = (int) VMMemory[128+i].getValue();
                }

                fw.close();
            }
            catch (IOException e) {
                machine.changeIOI(1L);
//                System.out.println("Error: " + e.getMessage());
            }
        }
        else if (outputType == 3) { // Išvedami žodžiuose esantys skaičiai ir atskiriami ženklais „ENTER“.
            try {
                FileWriter fw = new FileWriter("OUT.txt", true);
                int i = startPosition;
                String value = Long.toString(VMMemory[128+i].getValue());
                fw.write(value);
                fw.write(10);
                i++;

                while (!value.equals("0") && i < 128) {
                    value = Long.toString(VMMemory[128+i].getValue());
                    if (!value.equals("0")) {
                        fw.write(value);
                        fw.write(10);
                    } else {
                        break;
                    }
                    i++;
                }

                fw.close();
            }
            catch (IOException e) {
                machine.changeIOI(1L);
//                System.out.println("Error: " + e.getMessage());
            }
        } else {
            System.out.println("\nKlaida! Metodui writeOutput perduotas nepalaikomas duomenų įrašymo tipas.");
            System.out.println("Palaikomi tipai: 1, 2, 3. | Perduota reikšmė: " + outputType + ".");
        }
    }

    static boolean isNumeric(String value) { // value must be decimal.
        try {
            Long.parseLong(value);
            return true;
        }
        catch (NumberFormatException e) {
            return false;
        }
    }
}